rust 学习笔记

July 14, 2020

声明与可变性

在 rust 中声明和 javascript 有些类似, 基本可以总结为:

  1. 使用 let 声明变量, 使用 const 声明常量.
  2. 使用 mut 显式声明对变量可变性.
  3. 变量可重复声明, 后声明的变量覆盖前声明的变量. 重复定义的变量类型可不同.
  4. 常量除了具有不可变性外, 还是编译时完全确定的, 具体来说, 常量体现在内存中就是就是值固定的.
  5. mut 只定义了可变性, 但是变量的类型是不变的, 一旦推断类型就是不变的.

基本类型

rust 的基本类型有 4 中, 分别是整型, 浮点, 布尔和字符.

整型

整型分为有符号整型: i8, i16, i32, i64, i128, isize(取决于操作系统)

无符号整型: u8, u16, u32, u64, u128, usize(取决于操作系统)

如果不给定类型, 则首选推断类型为 i32

// 各进制写法
98_222 // decimal
0xff   // hex
0o77   // octal
0b1111_0000  //binary
b'A'   // byte 仅限u8

浮点

仅有 f32, f64

布尔

仅有 bool

字符

仅有 char, 大小为 4bytes

复合类型

复合类型原生有元组和数组

元组

形如(type1, type2, type3)的类型.

操作:

// 解构
let tup: (i32, f64, u8) = (500, 6.4, 1);
let (x, y, z) = tup;
// 访问
let x = tup.1;
let y = tup.2;
let z = tup.3;

数组

数组一旦声明, 长度就固定, 声明形如[type; length]

// 声明
let a: [i32; 5] = [1, 2, 3, 4, 5];
// 访问
let first = a[0];
let end = a[4];
// 初始化
let a = [3; 5];

函数

在 rust 中, 一个函数的定义如下

fn function_name(param1: type1, ...) -> [returnType] {
   ...
}

在 rust 中, 要理解返回值, 必须理解好语句和表达式, 表达式有返回值的, 而语句则没有返回值.

在 rust 中, 函数的返回值, 是由最后一个表达式的值决定的. 函数的定义是语句, 不返回任何值, 但是函数的调用则是表达式, 是可以返回值的, 这一定是必须要分清楚. 在这种严格的定义下可知, rsut 的赋值语句不返回任何值, 而 rsut 的代码块则是表达式, 所以在 rust 中会出现使用代码块来返回值的情况. 而控制流(if, loop, while, for)也被定义为表达式.

let a: u32 = { 4 };  // 代码块的返回值为最后一个表达式的值.
let a: u32 = if a == 3 { 3 } else if a == 4 { 4 };
let result = loop {
    counter += 1;
    if counter == 10 {
        break couter * 2;
    }
};

println!("The result is {}", result);

这种严格区分表达式和语句的理念可以有效理解 rust 在各种情况下的行为, 减少出错. 另语句必须使用分号作为结束.

所有权, 转移, 引用及借用

变量作用域: 当变量进入作用域时, 它是有效的, 并持续到离开作用域.

所有权是指一个变量拥有改变一个分配在堆上的数据的权力, 并且每时每刻, 当且仅有一个变量拥有改变同一份数据的能力.

所有权可以转移, 引用, 借用

// 转移, 所有权从s转移到s2上
let s = String::from("hello");
let s2 = s;
// 引用
let s = String::from("hello");
let s2 = &s;
// 借用, 借用是引用的一个特例, 特指将获取的引用作为函数参数
fn main() {
    let s = String::from("hello");
    change(&mut s);
}

fn change(some_string: &mut String) {
    some_string.push_str(", world");
}

而引用又分为可变引用和不可变引用, 可变引用可以改变数据, 但是不可变不能改变数据, 用 mut 指示.

在同一作用域下, 同一份数据的要么存在多个不可变引用, 要么存在单个可变引用

引用必须总是有效的,

这个模型旨在解决以往编程语言的几个重要问题:

  1. 一个变量如何释放分配的内存, rust 的答案是在离开作用域后就释放.
  2. 在多线程下, 如何避免数据竞争, rust 的答案是所有权机制是一个自然的读写锁模型, 可以有效避免竞争.
  3. 野指针, 野引用, rust 在编译阶段就不允许引用到不存在的数据.

Written by 梁伯豪